﻿#region Usings

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using DynamicBuilder;
using Omu.Awesome.Mvc;
using Rail.Net.Common;
using Rail.Net.Common.Model;
using Rail.Net.Common.Resources;

#endregion

namespace Rail.Net.Core.Model.Nonpersistent
{
    /// <summary>
    ///   Represents a search model
    /// </summary>
    [Serializable]
    [DataContract]
    public class SearchModel
    {
        private readonly Constants _constants = new Constants();

        #region Constructors

        public SearchModel()
        {
            IsQueryProcessed = false;

            Travelers = new List<TravelerModel>
                            {
                                new TravelerModel
                                    {
                                        Age = new ListableItem
                                        {
                                            Content = _constants.AgeContent,
                                            SelectedItem = _constants.AgeContent.SingleOrDefault(x => x.Name == (17).ToString())
                                        },
                                        Discount = new ListableItem
                                        {
                                            Content = _constants.DiscountContent,
                                            SelectedItem = _constants.DiscountContent.SingleOrDefault(x => x.Name == Global.MainModel_ListableItem_NoDiscount)
                                        }
                                    }
                            };
            PaymentType = new ListableItem
                              {
                                  Content = _constants.PaymentContent,
                                  SelectedItem = _constants.PaymentContent.SingleOrDefault(x => x.Name == Global.MainModel_ListableItem_CreditCardVisa)
                              };
            FromDate = DateTime.Now;
            IsQueryProcessed = false;
        }

        #endregion

        #region  Properties

        public bool IsQueryProcessed { get; set; }

        [Required(ErrorMessageResourceType = typeof (Global), ErrorMessageResourceName = "MainModel_FromStationRequired")]
        [Display(ResourceType = typeof (Global), Name = "MainModel_FromStation")]
        [UIHint("FromLookup")]
        [Lookup(Controller = "FromStationLookup", ClearButton = true)]
        [DataMember]
        public string FromStation { get; set; }

        [DataMember]
        public string FromStationName { get; set; }

        [Required(ErrorMessageResourceType = typeof (Global), ErrorMessageResourceName = "MainModel_ToStationRequired")]
        [Display(ResourceType = typeof (Global), Name = "MainModel_ToStation")]
        [UIHint("ToLookup")]
        [Lookup(Controller = "ToStationLookup", ClearButton = true)]
        [DataMember]
        public string ToStation { get; set; }

        [DataMember]
        public string ToStationName { get; set; }

        [Required(ErrorMessageResourceType = typeof (Global), ErrorMessageResourceName = "MainModel_FromDateRequired")]
        [Display(ResourceType = typeof (Global), Name = "MainModel_FromDate")]
        [DataMember]
        [DataType(DataType.DateTime)]
        public DateTime FromDate { get; set; }

        [Display(ResourceType = typeof (Global), Name = "MainModel_ToDate")]
        [DataMember]
        public DateTime? ToDate { get; set; }

        [Display(ResourceType = typeof (Global), Name = "MainModel_Traveler")]
        [DataMember]
        public List<TravelerModel> Travelers { get; private set; }

        [Required(ErrorMessageResourceType = typeof (Global), ErrorMessageResourceName = "MainModel_PaymentTypeRequired")]
        [Display(ResourceType = typeof (Global), Name = "MainModel_PaymentType")]
        [DataMember]
        public ListableItem PaymentType { get; set; }

        public List<int> GrownUpIndices
        {
            get
            {
                var result = new List<int>();
                for (var i = 0; i < Travelers.Count; i++)
                {
                    if (Travelers[i].AgeValue > 15)
                    {
                        result.Add(i);
                    }
                }
                return result;
            }
        }

        public List<int> ChildIndices
        {
            get
            {
                var result = new List<int>();
                for (var i = 0; i < Travelers.Count; i++)
                {
                    if (Travelers[i].AgeValue <= 15)
                    {
                        result.Add(i);
                    }
                }
                return result;
            }
        }

        public List<int> DiscountIndices
        {
            get
            {
                var result = new List<int>();
                for (var i = 0; i < Travelers.Count; i++)
                {
                    if (Travelers[i].HasDiscount)
                    {
                        result.Add(i);
                    }
                }
                return result;
            }
        }

        public int NumberOfAdults
        {
            get
            {
                return Travelers != null
                           ? Travelers.Count(traveler => Int32.Parse(traveler.Age.SelectedItem.Value) > 15)
                           : 0;
            }
        }

        public int NumberOfVorteilscards
        {
            get
            {
                return Travelers != null
                           ? Travelers.Count(
                               traveler => traveler.Discount.SelectedItem.Value == Constants.VorteilsCard ||
                                           traveler.Discount.SelectedItem.Value == Constants.VorteilsCard26)
                           : 0;
            }
        }

        public bool IsBusinesscardPayment
        {
            get { return PaymentType.SelectedItem.Value == Constants.BusinessCard; }
        }

        public bool IsBusinesscardBonusPayment
        {
            get
            {
                return PaymentType.SelectedItem.Value == Constants.BusinessCardBonus ||
                       PaymentType.SelectedItem.Value == Constants.BusinessCardSiemens;
            }
        }

        public DomesticTarifType DomesticTarifType
        {
            get
            {
                var result = DomesticTarifType.FullPrice;

                if (IsBusinesscardPayment)
                {
                    result = DomesticTarifType.Businesscard;
                }

                if (IsBusinesscardBonusPayment)
                {
                    result = DomesticTarifType.BusinesscardBonus;
                }

                if (NumberOfAdults > 2)
                {
                    result = DomesticTarifType.Minimax;
                }

                if (NumberOfVorteilscards > 0)
                {
                    result = DomesticTarifType.Vorteilscard;

                    if (result == DomesticTarifType.Minimax)
                    {
                        result = DomesticTarifType.MinimaxVc;
                    }

                    var numberOfAdults = NumberOfAdults;
                    var numberOfNotAdults = Travelers.Count - numberOfAdults;
                    if (numberOfAdults*2 >= numberOfNotAdults)
                    {
                        //result = DomesticTarifType.VorteilscardFamily;
                    }
                }
                return result;
            }
        }

        public string FromTransportPlanCacheKey
        {
            get
            {
                return String.Format("{0}#{1}#{2}", FromStation, ToStation, FromDate.ToString("yyyy-MM-dd"));
            }
        }

        public string FromProductOffersCacheKey
        {
            get
            {
                var travelers = Travelers.OrderBy(t => t.Age.SelectedItem.Value).OrderBy(t => t.Discount.SelectedItem.Value).Aggregate("", (current, travelerModel) => current + string.Format("{0}#{1}#", travelerModel.Age.SelectedItem.Value, travelerModel.Discount.SelectedItem.Value));
                return travelers + FromTransportPlanCacheKey;
            }
        }

        public string ToTransportPlanCacheKey
        {
            get
            {
                return String.Format("{0}#{1}#{2}", ToStation, FromStation, ToDate.Value.ToString("yyyy-MM-dd"));
            }
        }

        public string ToProductOffersCacheKey
        {
            get
            {
                var travelers = Travelers.OrderBy(t => t.Age.SelectedItem.Value).OrderBy(t => t.Discount.SelectedItem.Value).Aggregate("", (current, travelerModel) => current + string.Format("{0}#{1}#", travelerModel.Age.SelectedItem.Value, travelerModel.Discount.SelectedItem.Value));
                return travelers + ToTransportPlanCacheKey;
            }
        }

        #endregion

        #region Methods

        public Xml PrepareTransportPlanXml(bool forwardDirection)
        {
            dynamic xml = new Xml();
            xml.Declaration();
            xml.ReqC(
                new {prod = "String", lang = "DE"},
                Xml.Fragment(ReqC =>
                                 {
                                     ReqC.ConReq(
                                         Xml.Fragment(ConReq =>
                                                          {
                                                              ConReq.Start(
                                                                  Xml.Fragment(Start =>
                                                                                   {
                                                                                       Start.Station(
                                                                                           new
                                                                                               {
                                                                                                   externalId =
                                                                                               (forwardDirection
                                                                                                    ? FromStation
                                                                                                    : ToStation)
                                                                                               });
                                                                                       Start.Prod(
                                                                                           new
                                                                                               {
                                                                                                   prod =
                                                                                               "1111110010000000",
                                                                                                   bike = "0",
                                                                                                   sleeper = "0",
                                                                                                   couchette = "0",
                                                                                                   direct = "0"
                                                                                               });
                                                                                   }));
                                                              ConReq.Dest(
                                                                  Xml.Fragment(
                                                                      Dest => Dest.Station(
                                                                          new
                                                                              {
                                                                                  externalId =
                                                                              (forwardDirection
                                                                                   ? ToStation
                                                                                   : FromStation)
                                                                              })));
                                                              ConReq.ReqT(
                                                                  new
                                                                      {
                                                                          a = "0",
                                                                          date =
                                                                      (forwardDirection ? FromDate : ToDate.Value).
                                                                      ToString("yyyy-MM-dd"),
                                                                          time = "00:00"
                                                                      });
                                                              ConReq.RFlags(new {b = "0", f = "6", nrChabges = "4"});
                                                          }));
                                 }));
            return xml;
        }

        public void FixDropdownListNames(List<NameValuePair> fromStations, List<NameValuePair> toStations)
        {
            foreach (var travelerModel in Travelers)
            {
                try
                {
                    travelerModel.Age.SelectedItem.Name =
                        _constants.AgeContent.SingleOrDefault(x => x.Value == travelerModel.Age.SelectedItem.Value).Name;
                }
                catch (NullReferenceException e)
                {
                    // suppress the exception
                }


                try
                {
                    travelerModel.Discount.SelectedItem.Name =
                        _constants.DiscountContent.SingleOrDefault(
                            x => x.Value == travelerModel.Discount.SelectedItem.Value).Name;
                }
                catch (NullReferenceException e)
                {
                    // suppress the exception
                }
            }
            if (fromStations != null)
            {

                try
                {
                    FromStationName = fromStations.FirstOrDefault(item => item.Value == FromStation).Name;
                }
                catch (NullReferenceException e)
                {
                    // suppress the exception
                }
            }
            if (toStations != null)
            {
                try
                {
                    ToStationName = toStations.FirstOrDefault(item => item.Value == ToStation).Name;
                }
                catch (NullReferenceException e)
                {
                    // suppress the exception
                }
            }
        }

        #endregion
    }
}